#Construir los xml de respuesta para los listados
#Construir el protocolo de respuestas , los codigos de mensaje, la estructura

from google.appengine.ext import blobstore
from google.appengine.ext.webapp import blobstore_handlers
from google.appengine.ext.webapp import template
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
from google.appengine.api import images
from xml.dom import minidom
from xml.dom.minidom import parse, parseString
import google.appengine.ext.db
import cgi
import wsgiref.handlers
import datetime
import pprint
import os
import pygeoip
import distance
import urllib
import urllib2
import urlparse
import sys


GEOIP = pygeoip.Database('GeoIP.dat')

class Place (db.Model):
  name = db.StringProperty()
  latitude = db.FloatProperty()
  longitude = db.FloatProperty()
  tc = db.DateTimeProperty(auto_now_add=True)
  ts = db.DateTimeProperty(auto_now_add=True)
  
class Product(db.Model):
  name = db.StringProperty()
  origin = db.StringProperty()
  begin_season = db.StringProperty()
  end_season = db.StringProperty()
  comments = db.Text()
  blob = blobstore.BlobReferenceProperty()
  imageurl = db.LinkProperty()
  description = db.Text()
  tc = db.DateTimeProperty(auto_now_add=True)
  ts = db.DateTimeProperty(auto_now_add=True)

class ProductImage(db.Model):
  blob = blobstore.BlobReferenceProperty()
  imageurl = db.LinkProperty()
  name = db.StringProperty()
  description = db.StringProperty()
  product = db.ReferenceProperty(Product)
  available = db.BooleanProperty()
  ts = db.DateTimeProperty(auto_now_add=True)

class Restaurant(db.Model):
  name = db.StringProperty()
  address = db.StringProperty()
  city = db.StringProperty()
  country = db.StringProperty()
  latitude = db.FloatProperty()
  longitude = db.FloatProperty()
  description = db.StringProperty()
  blob = blobstore.BlobReferenceProperty()
  imageurl = db.LinkProperty()
  tc = db.DateTimeProperty(auto_now_add=True)
  ts = db.DateTimeProperty(auto_now_add=True)

class RestaurantImage(db.Model):
  blob = blobstore.BlobReferenceProperty()
  imageurl = db.LinkProperty()
  name = db.StringProperty()
  nameRestaurant = db.StringProperty()
  description = db.StringProperty()
  restaurant = db.ReferenceProperty(Restaurant)
  available = db.BooleanProperty()
  ts = db.DateTimeProperty(auto_now_add=True)

class RestaurantDescriptions(db.Model):
  name = db.StringProperty()
  nameplace = db.StringProperty()
  latitude = db.FloatProperty()
  longitude = db.FloatProperty()
  description = db.StringProperty()
  restaurant = db.ReferenceProperty(Restaurant)
  tc = db.DateTimeProperty(auto_now_add=True)
  ts = db.DateTimeProperty(auto_now_add=True)



#class MainPage(webapp.RequestHandler):
#  def get(self):
#    restaurants = Restaurant.all()
#    products = Product.all()
#    self.response.headers['Content-Type'] = 'text/html'
#    self.response.out.write(
#      template.render('helloworld.html',
#                      {'restaurantes':restaurants,
#                      'productos':products}))

class MainPage(webapp.RequestHandler):
  def get(self):
    upload_url = blobstore.create_upload_url('/uploadrestaurant')
    self.response.out.write('<html><body>')
    self.response.out.write('<h2>Add a Restaurant</h2>')
    self.response.out.write('<table border=1"><form action="%s" method="POST" enctype="multipart/form-data">' % upload_url)
    self.response.out.write("""<tr><td>
                            Ingrese el nombre del restaurante:
                            </td><td>
                            <input type="text" name="name"><br>
                            </td><tr><td>
                            Ingrese la localizacion del restaurante:
                            </td><td>
                            <input type="text" name="nameplace"><br>
                            </td><tr><td>
                            Ingrese la latitud de las coordenadas posicion restuarante:
                            </td><td>
                            <input type="text" name="latitude"><br>
                            </td><tr><td>
                            Ingrese la longitud de las coordenadas de posicion restaurante:
                            </td><td>
                            <input type="text" name="longitude"><br>
                            </td><tr><td>
                            Ingrese la descripcion del restaurante:
                            </td><td>
                            <input type="text" name="description"><br>
                            </td><tr><td>
                            Upload File:
                            </td><td>
                            <input type="file" name="file"><br>
                            </td></tr><tr><td></td><td>
                            <input type="submit" value="enviar"><br>
                            </td></tr></form></table>""")
    upload_url = blobstore.create_upload_url('/uploadproduct')
    self.response.out.write('<h2>Add a Product</h2>')
    self.response.out.write('<table border=1"><form action="%s" method="POST" enctype="multipart/form-data">' % upload_url)
    self.response.out.write("""<tr><td>
                            Ingrese el nombre del producto:
                            </td><td>
                            <input type="text" name="name"><br>
                            </td><tr><td>
                            Ingrese el origen del restaurante:
                            </td><td>
                            <input type="text" name="origin"><br>
                            </td><tr><td>
                            Ingrese el mes de comienzo de la temporada del producto:
                            </td><td>
                            <input type="text" name="begin_season"><br>
                            </td><tr><td>
                            Ingrese el mes de fin de la temporada del producto:
                            </td><td>
                            <input type="text" name="end_season"><br>
                            </td><tr><td>
                            Ingrese la descripcion del producto:
                            </td><td>
                            <input type="text" name="description"><br>
                            </td><tr><td>
                            Upload File:
                            </td><td>
                            <input type="file" name="file"><br>
                            </td></tr><tr><td></td><td>
                            <input type="submit" value="enviar"><br>
                            </td></tr></form></table>""")
    self.response.out.write('<br><br><h2>RESTAURANTS</h2><table border="1"><tr><td>')
    for rest in Restaurant.all():                
      self.response.out.write('<div><a href="/detallesrest?key=%s' % str(rest.key()))
      self.response.out.write('&id=%s"' % str(rest.key().id()))
      self.response.out.write('<b><h3><i>%s</i></h3></div></a>' % rest.name)
      self.response.out.write('<div><img src="%s=s128"/>' % rest.imageurl)
      self.response.out.write('<div>Image URL: <i>%s</i></div>' % rest.imageurl)
    self.response.out.write('</td></tr></table><br>')
    self.response.out.write('<br><br><h2>PRODUCTS</h2><table border="1"><tr><td>')
    for prod in Product.all():
      self.response.out.write('<div><a href="/detallesprod?key=%s' % str(prod.key()))
      self.response.out.write('&id=%s"' % str(prod.key().id()))
      self.response.out.write('<b><h3><i>%s</i></h3></div></a>' % prod.name)
      self.response.out.write('<div><img src="%s=s96"/>' % prod.imageurl)
      self.response.out.write('<div><b>Image URL: </b><i>%s</i></div>' % prod.imageurl)
    self.response.out.write('</td></tr></table><br>') 
    self.response.out.write('<div><a href="/geolocalization">Localization</a></div>')
    self.response.out.write('<div><a href="/closestrestaurant">Restaurantes Cercanos</a></div>')
    formurl = '/geocode'
    self.response.out.write('<table border=1"><form action="%s" method="POST" enctype="multipart/form-data">' % formurl)
    self.response.out.write("""<tr><td>
                            Direccion a codificar:
                            </td><td>
                            <input type="text" name="address"><br>
                            </td></tr><tr><td></td><td>
                            <input type="submit" value="enviar"><br>
                            </td></tr></form></table>""")

    self.response.out.write('</body></html>')

class UploadHandlerRestaurant(blobstore_handlers.BlobstoreUploadHandler):
  def post(self):
    upload_files = self.get_uploads('file')  # 'file' is file upload field in the form
    blob_info = upload_files[0]
    rest = Restaurant()
    rest.name = self.request.get('name')
    rest.nameplace = self.request.get('nameplace')
    rest.latitude = float(self.request.get('latitude'))
    rest.longitude = float(self.request.get('longitude'))
    rest.description = self.request.get('description')
    rest.blob = blob_info.key()
    rest.imageurl = images.get_serving_url(str(blob_info.key()))
    rest.put()
    restIma = RestaurantImage()
    restIma.blob = rest.blob
    restIma.imageurl = rest.imageurl
    restIma.name = rest.name
    restIma.description = rest.description
    restIma.restaurant = rest.key()
    restIma.available = True
    restIma.put()
    self.redirect('/')

class UploadHandlerProduct(blobstore_handlers.BlobstoreUploadHandler):
  def post(self):
    upload_files = self.get_uploads('file')  # 'file' is file upload field in the form
    blob_info = upload_files[0]
    product = Product()
    product.name = self.request.get('name')
    product.origin = self.request.get('origin')
    product.begin_season = self.request.get('begin_season')
    product.end_season = self.request.get('end_season')
    product.description = self.request.get('description')
    product.blob = blob_info.key()
    product.imageurl = images.get_serving_url(str(blob_info.key()))
    product.put()
    productIma = ProductImage()
    productIma.blob = product.blob
    productIma.imageurl = product.imageurl
    productIma.name = product.name
    productIma.description = product.description
    productIma.product = product.key()
    productIma.available = True
    productIma.put()
    self.redirect('/')

class MoreRestPics(blobstore_handlers.BlobstoreUploadHandler):
  def post(self):
    upload_files = self.get_uploads('file')  # 'file' is file upload field in the form
    blob_info = upload_files[0]
    restIma = RestaurantImage()
    restIma.blob = blob_info.key()
    restIma.imageurl = images.get_serving_url(str(blob_info.key()))
    restIma.name = self.request.get('name')
    restIma.description = self.request.get('description')
    rest = Restaurant.get_by_id(int(self.request.get('id')))
    restIma.restaurant = rest.key()
    restIma.available = True
    restIma.put()
    self.redirect('/')

class MoreProdPics(blobstore_handlers.BlobstoreUploadHandler):
  def post(self):
    upload_files = self.get_uploads('file')  # 'file' is file upload field in the form
    blob_info = upload_files[0]
    prodIma = ProductImage()
    prodIma.blob = blob_info.key()
    prodIma.imageurl = images.get_serving_url(str(blob_info.key()))
    prodIma.name = self.request.get('name')
    prodIma.description = self.request.get('description')
    prod = Product.get_by_id(int(self.request.get('id')))
    prodIma.product = prod.key()
    prodIma.available = True
    prodIma.put()
    self.redirect('/')

class DetailsRestHandler(webapp.RequestHandler):
  def get(self):
    implementacion_DOM = minidom.getDOMImplementation()
    xml_document = implementacion_DOM.createDocument(None, "response", None)
    raiz_documento = xml_document.documentElement
    rest = Restaurant.get_by_id(int(self.request.get('id')))
    rest = RestaurantImage.all().filter('restaurant = ', rest.key())
    rest = rest.fetch(10)
    nodo = xml_document.createElement("images")
    for res in rest:
      self.response.out.write('<div><b><h3><i>%s</i></h3></div></a>' % res.name)
      self.response.out.write('<div><img src="%s=s128"/>' % res.imageurl)
      self.response.out.write('<div>Image URL: <i>%s</i></div></div>' % res.imageurl)
      element = xml_document.createElement("nombre")
      element.appendChild(xml_document.createTextNode(res.name))
      elemento = xml_document.createElement("imagen")
      elemento.appendChild(xml_document.createTextNode(res.imageurl))
      nodo.appendChild(elemento)
      nodo.appendChild(element)
    raiz_documento.appendChild(nodo)
    pretty_xml_as_string = xml_document.toprettyxml()
    #IMPRIMIR EL XML CON LAS IMAGENES Y LOS NOMBRES
    #print pretty_xml_as_string
    upload_url = blobstore.create_upload_url('/onemorerestpic')
    self.response.out.write('<html><body>')
    self.response.out.write('<table border=1"><form action="%s" method="POST" enctype="multipart/form-data">' % upload_url)
    self.response.out.write("""<tr><td>
                              Ingrese el nombre de la foto:
                                      </td><td>""")
    self.response.out.write('<input type="hidden" name="id" value="%s"> ' % self.request.get('id'))
    self.response.out.write("""<input type="text" name="name"><br>
                                      </td><tr><td>
                                      Ingrese la descripcion del restaurante:
                                      </td><td>
                                      <input type="text" name="description"><br>
                                      </td><tr><td>
                                      Upload File:
                                      </td><td>
                                      <input type="file" name="file"><br>
                                      </td></tr><tr><td></td><td>
                                      <input type="submit" value="enviar"><br>
                                      </td></tr></form></table>""")
class DetailsProdHandler(webapp.RequestHandler):
  def get(self):
    implementacion_DOM = minidom.getDOMImplementation()
    xml_document = implementacion_DOM.createDocument(None, "response", None)
    raiz_documento = xml_document.documentElement
    nodo = xml_document.createElement("images")
    prod = Product.get_by_id(int(self.request.get('id')))
    prod = ProductImage.all().filter('product = ', prod.key())
    prod = prod.fetch(10)
    for pro in prod:
      self.response.out.write('<div><b><h3><i>%s</i></h3></div></a>' % pro.name)
      self.response.out.write('<div><img src="%s=s128"/>' % pro.imageurl)
      self.response.out.write('<div>Image URL: <i>%s</i></div></div>' % pro.imageurl)
      element = xml_document.createElement("nombre")
      element.appendChild(xml_document.createTextNode(pro.name))
      elemento = xml_document.createElement("imagen")
      elemento.appendChild(xml_document.createTextNode(pro.imageurl))
      nodo.appendChild(elemento)
      nodo.appendChild(element)
    raiz_documento.appendChild(nodo)
    pretty_xml_as_string = xml_document.toprettyxml()
    #IMPRIMIR EL XML CON LAS IMAGENES Y LOS NOMBRES
    #print pretty_xml_as_string
    upload_url = blobstore.create_upload_url('/onemoreprodpic')
    self.response.out.write('<html><body>')
    self.response.out.write('<table border=1"><form action="%s" method="POST" enctype="multipart/form-data">' % upload_url)
    self.response.out.write("""<tr><td>
                              Ingrese el nombre de la foto:
                                      </td><td>""")
    self.response.out.write('<input type="hidden" name="id" value="%s"> ' % self.request.get('id'))
    self.response.out.write("""<input type="text" name="name"><br>
                                      </td><tr><td>
                                      Ingrese la descripcion del producto:
                                      </td><td>
                                      <input type="text" name="description"><br>
                                      </td><tr><td>
                                      Upload File:
                                      </td><td>
                                      <input type="file" name="file"><br>
                                      </td></tr><tr><td></td><td>
                                      <input type="submit" value="enviar"><br>
                                      </td></tr></form></table>""")    

class UpdateProduct(webapp.RequestHandler):
  def post(self):
    product = Product.get_by_id(int(self.request.get('key')))
    product.name = self.request.get('name')
    product.origin = self.request.get('origin')
    product.begin_season = self.request.get('begin_season')
    product.end_season = self.request.get('end_season')
    product.description = self.request.get('description')
    product.put()
    self.redirect('/listadoproductos')

class UpdateRestaurant(webapp.RequestHandler):
  def post(self):
    restaurant = Restaurant.get_by_id(int(self.request.get('key')))
    restaurant.name = self.request.get('name')
    restaurant.nameplace = self.request.get('nameplace')
    restaurant.latitude = float(self.request.get('latitude'))
    restaurant.longitude = float(self.request.get('longitude'))
    restaurant.description = self.request.get('description')
    restaurant.put()
    self.redirect('/listadoproductos')

class ProductList(webapp.RequestHandler):
  def get(self):
    products = Product.all()
    restaurants = Restaurant.all()
    self.response.headers['Content-Type'] = 'text/html'
    self.response.out.write(
      template.render('listados.html',
                    {'productos':products,'restaurantes':restaurants}))


class WhatsTheClosestRestaurant(webapp.RequestHandler):
  def get(self):
    implementacion_DOM = minidom.getDOMImplementation()
    xml_document = implementacion_DOM.createDocument(None, "response", None)
    raiz_documento = xml_document.documentElement
    nodo = xml_document.createElement("restaurants")
    latitude1 = self.request.get('latitude')
    longitude1 = self.request.get('longitude')
    if not latitude1: 
      latitude1 = 40.21
    if not longitude1:
      longitude1 = -3.68
    restaurants = Restaurant.all()
    indice = 0
    dist = []
    keys = []
    for rest in restaurants:
      dist.append(indice)
      dist[indice] = distance.distance_on_unit_sphere(latitude1,longitude1,rest.latitude,rest.longitude)
      keys.append(indice)
      keys[indice] = rest.key()
      indice = indice+1
    dista = distance.quicksort(dist,keys)
    dist = dista[0]
    keys = dista[1]
    indice = 0
    while indice < (len(dist)):
      restaurant = Restaurant.get(keys[indice])
      self.response.out.write('<div><b><h3><i>%s</i></h3></div>' % restaurant.name)
      self.response.out.write('<div><b>Distancia:<h4><i>%s</i></h4></div>' % dist[indice])
      self.response.out.write('<div><img src="%s=s128"/>' % restaurant.imageurl)
      self.response.out.write('<div>Image URL: <i>%s</i></div>' % restaurant.imageurl)
      node = xml_document.createElement("restaurant")
      element = xml_document.createElement("nombre")
      element.appendChild(xml_document.createTextNode(restaurant.name))
      elemento = xml_document.createElement("distancia")
      elemento.appendChild(xml_document.createTextNode(str(dist[indice])))
      elemen = xml_document.createElement("image")
      elemen.appendChild(xml_document.createTextNode(restaurant.imageurl))
      eleme = xml_document.createElement("description")
      eleme.appendChild(xml_document.createTextNode(restaurant.description))
      node.appendChild(elemento)
      node.appendChild(element)
      node.appendChild(elemen)
      node.appendChild(eleme)
      nodo.appendChild(node)
      indice = indice+1
    raiz_documento.appendChild(nodo)
    pretty_xml_as_string = xml_document.toprettyxml()
    #IMPRIMIR EL XML CON LAS IMAGENES Y LOS NOMBRES
    #print pretty_xml_as_string
      
class LookupHandler(webapp.RequestHandler):
  def get(self):
    implementacion_DOM = minidom.getDOMImplementation()
    xml_document = implementacion_DOM.createDocument(None, "response", None)
    raiz_documento = xml_document.documentElement
    nodo = xml_document.createElement("location")
    info = GEOIP.lookup(self.request.remote_addr)
    if not info.country:
      msg = 'Could not locate city for ' + self.request.remote_addr
    else:
      msg = 'Country for %s is %s' % (self.request.remote_addr, info.country)
      element = xml_document.createElement("country")
      element.appendChild(xml_document.createTextNode(info.country))
      #elemen = xml_document.createElement("region")
      #elemen.appendChild(xml_document.createTextNode(info.region))
      #eleme = xml_document.createElement("city")
      #eleme.appendChild(xml_document.createTextNode(info.city))
      #elem = xml_document.createElement("latitude")
      #elem.appendChild(xml_document.createTextNode(info.latitude))
      #ele = xml_document.createElement("longitude")
      #ele.appendChild(xml_document.createTextNode(info.longitude))
      nodo.appendChild(element)
      #nodo.appendChild(elemen)
      #nodo.appendChild(eleme)
      #nodo.appendChild(elem)
      #nodo.appendChild(ele)
      raiz_documento.appendChild(nodo)
      pretty_xml_as_string = xml_document.toprettyxml()
      #IMPRIMIR EL XML CON LAS IMAGENES Y LOS NOMBRES
      print pretty_xml_as_string
      #msg = msg + '<br>Region for %s is %s' % (self.request.remote_addr, info.region)
      #msg = msg + '<br>City for %s is %s' % (self.request.remote_addr, info.city)
      #msg = msg + '<br> Latitude for %s is %s' % (self.request.remote_addr, info.latitude)
      #msg = msg + '<br> Longitude for %s is %s' % (self.request.remote_addr, info.longitude)
    self.response.out.write(msg)

class GeoCoding(webapp.RequestHandler):
  def post(self):
    implementacion_DOM = minidom.getDOMImplementation()
    xml_document = implementacion_DOM.createDocument(None, "response", None)
    raiz_documento = xml_document.documentElement
    nodo = xml_document.createElement("coordenates")
    address = self.request.get('address')
    address = urllib.urlencode({'address': address})
    url = "http://maps.google.com/maps/api/geocode/xml?"+address+"&sensor=false&language=es"
    try:
      result = urllib2.urlopen(url)
      xml = result.read()
      result.close()
      dom = parseString(xml)
      coordenadas = [0,1]
      lat = dom.getElementsByTagName('lat')[0].toxml()
      lng = dom.getElementsByTagName('lng')[0].toxml()
      lat=float(lat.replace('<lat>','').replace('</lat>',''))
      lng=float(lng.replace('<lng>','').replace('</lng>',''))
      element = xml_document.createElement("latitude")
      element.appendChild(xml_document.createTextNode(str(lat)))
      elemen = xml_document.createElement("longitude")
      elemen.appendChild(xml_document.createTextNode(str(lng)))
      nodo.appendChild(element)
      nodo.appendChild(elemen)
      raiz_documento.appendChild(nodo)
      pretty_xml_as_string = xml_document.toprettyxml()
      #IMPRIMIR EL XML CON LAS IMAGENES Y LOS NOMBRES
      #print pretty_xml_as_string
      coordenadas[0] = lat
      coordenadas[1] = lng
      return coordenadas
    except urllib2.URLError, e:
      print e

def main():
  application = webapp.WSGIApplication([('/', MainPage),
                                        ('/updateres', UpdateRestaurant),
                                        ('/updatepro', UpdateProduct),
                                        ('/listadoproductos', ProductList),
                                        ('/uploadrestaurant', UploadHandlerRestaurant),
                                        ('/uploadproduct', UploadHandlerProduct),
                                        ('/detallesrest', DetailsRestHandler),
                                        ('/detallesprod', DetailsProdHandler),
                                        ('/onemorerestpic', MoreRestPics),
                                        ('/onemoreprodpic', MoreProdPics),
                                        ('/geolocalization', LookupHandler),
                                        ('/closestrestaurant', WhatsTheClosestRestaurant),
                                        ('/geocode', GeoCoding)
                                       ],
                                       debug=True)
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == "__main__":
    main()



